﻿#region zh-CHS 2006 - 2010 DemoSoft 团队 | en 2006-2010 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the MMOSE(Massively Multiplayer Online Server Engine) for .NET.
//
//                              2006-2010 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Demo.Mmose.Core.Common;
using System.Threading;
#endregion

namespace Demo.Mmose.Core.Common.SafeCollections
{
    /// <summary>
    /// 
    /// </summary>
    public class SafeSortedList<KeyT, ValueT> : IEnumerable<KeyValuePair<KeyT, ValueT>>
    {
        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 
        /// </summary>
        public SafeSortedList()
        {
            m_SortedList = new SortedList<KeyT, ValueT>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="comparer"></param>
        public SafeSortedList( IComparer<KeyT> comparer )
        {
            m_SortedList = new SortedList<KeyT, ValueT>( comparer );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dictionary"></param>
        public SafeSortedList( IDictionary<KeyT, ValueT> dictionary )
        {
            m_SortedList = new SortedList<KeyT, ValueT>( dictionary );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="capacity"></param>
        public SafeSortedList( int capacity )
        {
            m_SortedList = new SortedList<KeyT, ValueT>( capacity );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dictionary"></param>
        /// <param name="comparer"></param>
        public SafeSortedList( IDictionary<KeyT, ValueT> dictionary, IComparer<KeyT> comparer )
        {
            m_SortedList = new SortedList<KeyT, ValueT>( dictionary, comparer );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="capacity"></param>
        /// <param name="comparer"></param>
        public SafeSortedList( int capacity, IComparer<KeyT> comparer )
        {
            m_SortedList = new SortedList<KeyT, ValueT>( capacity, comparer );
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties
        /// <summary>
        /// 
        /// </summary>
        public int Capacity
        {
            get
            {
                return m_SortedList.Capacity;
            }
            set
            {
                m_LockSortedList.EnterWriteLock();
                try
                {
                    m_SortedList.Capacity = value;
                }
                finally
                {
                    m_LockSortedList.ExitWriteLock();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public int Count
        {
            get { return m_SortedList.Count; }
        }

        /// <summary>
        /// 
        /// </summary>
        public IComparer<KeyT> Comparer
        {
            get { return m_SortedList.Comparer; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public ValueT this[KeyT key]
        {
            get
            {
                ValueT returnValue = default( ValueT );

                m_LockSortedList.EnterReadLock();
                try
                {
                    returnValue = m_SortedList[key];
                }
                finally
                {
                    m_LockSortedList.ExitReadLock();
                }

                return returnValue;
            }
            set
            {
                m_LockSortedList.EnterWriteLock();
                try
                {
                    m_SortedList[key] = value;

                    m_bIsValueChange = true;
                }
                finally
                {
                    m_LockSortedList.ExitWriteLock();
                }
            }
        }
        #endregion

        #region zh-CHS 共有方法 | en Public Methods

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private SortedList<KeyT, ValueT> m_SortedList = null;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockSortedList = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add( KeyT key, ValueT value )
        {
            m_LockSortedList.EnterWriteLock();
            try
            {
                m_SortedList.Add( key, value );

                m_bIsValueChange = true;
            }
            finally
            {
                m_LockSortedList.ExitWriteLock();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Clear()
        {
            m_LockSortedList.EnterWriteLock();
            try
            {
                m_SortedList.Clear();

                m_bIsValueChange = true;
            }
            finally
            {
                m_LockSortedList.ExitWriteLock();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey( KeyT key )
        {
            m_LockSortedList.EnterReadLock();
            try
            {
                m_SortedList.ContainsKey( key );
            }
            finally
            {
                m_LockSortedList.ExitReadLock();
            }

            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool ContainsValue( ValueT value )
        {
            m_LockSortedList.EnterReadLock();
            try
            {
                m_SortedList.ContainsValue( value );
            }
            finally
            {
                m_LockSortedList.ExitReadLock();
            }

            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public int IndexOfKey( KeyT key )
        {
            int returnInt = -1;

            m_LockSortedList.EnterReadLock();
            try
            {
                returnInt = m_SortedList.IndexOfKey( key );
            }
            finally
            {
                m_LockSortedList.ExitReadLock();
            }

            return returnInt;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public int IndexOfValue( ValueT value )
        {
            int returnInt = -1;

            m_LockSortedList.EnterReadLock();
            try
            {
                returnInt = m_SortedList.IndexOfValue( value );
            }
            finally
            {
                m_LockSortedList.ExitReadLock();
            }

            return returnInt;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Remove( KeyT key )
        {
            bool resultBool = false;

            m_LockSortedList.EnterWriteLock();
            try
            {
                resultBool = m_SortedList.Remove( key );

                if ( resultBool == true )
                    m_bIsValueChange = true;
            }
            finally
            {
                m_LockSortedList.ExitWriteLock();
            }

            return resultBool;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        public void RemoveAt( int index )
        {
            m_LockSortedList.EnterWriteLock();
            try
            {
                m_SortedList.RemoveAt( index );

                m_bIsValueChange = true;
            }
            finally
            {
                m_LockSortedList.ExitWriteLock();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool TryGetValue( KeyT key, out ValueT value )
        {
            value = default( ValueT );

            bool returnValue = false;

            m_LockSortedList.EnterReadLock();
            try
            {
                returnValue = m_SortedList.TryGetValue( key, out value );
            }
            finally
            {
                m_LockSortedList.ExitReadLock();
            }

            return returnValue;
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        #region zh-CHS 私有常量 | en Private Constants
        /// <summary>
        /// 
        /// </summary>
        private readonly static KeyT[] s_ZeroKeyArray = new KeyT[0];
        /// <summary>
        /// 
        /// </summary>
        private readonly static ValueT[] s_ZeroValueArray = new ValueT[0];
        /// <summary>
        /// 
        /// </summary>
        private readonly static KeyValuePair<KeyT, ValueT>[] s_ZeroKeyValuePairArray = new KeyValuePair<KeyT, ValueT>[0];
        #endregion
        /// <summary>
        /// 
        /// </summary>
        private volatile KeyT[] m_KeyArray = s_ZeroKeyArray;
        /// <summary>
        /// 
        /// </summary>
        private volatile ValueT[] m_ValueArray = s_ZeroValueArray;
        /// <summary>
        /// 
        /// </summary>
        private volatile KeyValuePair<KeyT, ValueT>[] m_KeyValuePairArray = s_ZeroKeyValuePairArray;
        /// <summary>
        /// 
        /// </summary>
        private volatile bool m_bIsValueChange = true;
        #endregion

        #region zh-CHS 私有方法 | en Private Methods
        /// <summary>
        /// 
        /// </summary>
        private void InternalToCached()
        {
            if ( m_bIsValueChange == false )
                return;

            m_LockSortedList.EnterReadLock();
            try
            {
                if ( m_bIsValueChange == true )
                {
                    m_KeyArray = new KeyT[m_SortedList.Count];
                    m_ValueArray = new ValueT[m_SortedList.Count];
                    m_KeyValuePairArray = new KeyValuePair<KeyT, ValueT>[m_SortedList.Count];

                    int iIndex = 0;
                    foreach ( KeyValuePair<KeyT, ValueT> keyValuePair in m_SortedList )
                    {
                        m_KeyArray[iIndex] = keyValuePair.Key;
                        m_ValueArray[iIndex] = keyValuePair.Value;
                        m_KeyValuePairArray[iIndex] = keyValuePair;
                        ++iIndex;
                    }

                    // 最后设置
                    m_bIsValueChange = false;
                }
            }
            finally
            {
                m_LockSortedList.ExitReadLock();
            }
        }
        #endregion
        /// <summary>
        /// 这里假设读非常多，写比较少。 
        /// </summary>
        /// <returns></returns>
        [MultiThreadedWarning( "zh-CHS", "当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public KeyValuePair<KeyT, ValueT>[] ToArray()
        {
            InternalToCached();

            return m_KeyValuePairArray;
        }

        /// <summary>
        /// 这里假设读非常多，写比较少。 
        /// </summary>
        /// <returns></returns>
        [MultiThreadedWarning( "zh-CHS", "当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public ValueT[] ToArrayValues()
        {
            InternalToCached();

            return m_ValueArray;
        }

        /// <summary>
        /// 这里假设读非常多，写比较少。 
        /// </summary>
        /// <returns></returns>
        [MultiThreadedWarning( "zh-CHS", "当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public KeyT[] ToArrayKeys()
        {
            InternalToCached();

            return m_KeyArray;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public KeyValuePair<KeyT, ValueT>[] ToArrayAndClear()
        {
            KeyValuePair<KeyT, ValueT>[] keyValuePairArray = s_ZeroKeyValuePairArray;

            m_LockSortedList.EnterWriteLock();
            try
            {
                if ( m_bIsValueChange == true )
                {
                    keyValuePairArray = new KeyValuePair<KeyT, ValueT>[m_SortedList.Count];

                    int iIndex = 0;
                    foreach ( KeyValuePair<KeyT, ValueT> keyValuePair in m_SortedList )
                    {
                        keyValuePairArray[iIndex] = keyValuePair;
                        ++iIndex;
                    }

                    // 最后设置
                    m_bIsValueChange = false;
                }
                else
                    keyValuePairArray = m_KeyValuePairArray;

                // 清空
                m_SortedList.Clear();
                m_KeyArray = s_ZeroKeyArray;
                m_ValueArray = s_ZeroValueArray;
                m_KeyValuePairArray = s_ZeroKeyValuePairArray;
            }
            finally
            {
                m_LockSortedList.ExitWriteLock();
            }

            return keyValuePairArray;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public ValueT[] ToArrayValuesAndClear()
        {
            ValueT[] valueArray = s_ZeroValueArray;

            m_LockSortedList.EnterWriteLock();
            try
            {
                if ( m_bIsValueChange == true )
                {
                    valueArray = new ValueT[m_SortedList.Count];

                    int iIndex = 0;
                    foreach ( KeyValuePair<KeyT, ValueT> keyValuePair in m_SortedList )
                    {
                        valueArray[iIndex] = keyValuePair.Value;
                        ++iIndex;
                    }

                    // 最后设置
                    m_bIsValueChange = false;
                }
                else
                    valueArray = m_ValueArray;

                // 清空
                m_SortedList.Clear();
                m_KeyArray = s_ZeroKeyArray;
                m_ValueArray = s_ZeroValueArray;
                m_KeyValuePairArray = s_ZeroKeyValuePairArray;
            }
            finally
            {
                m_LockSortedList.ExitWriteLock();
            }

            return valueArray;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public KeyT[] ToArrayKeysAndClear()
        {
            KeyT[] keyArray = s_ZeroKeyArray;

            m_LockSortedList.EnterWriteLock();
            try
            {
                if ( m_bIsValueChange == true )
                {
                    keyArray = new KeyT[m_SortedList.Count];

                    int iIndex = 0;
                    foreach ( KeyValuePair<KeyT, ValueT> keyValuePair in m_SortedList )
                    {
                        keyArray[iIndex] = keyValuePair.Key;
                        ++iIndex;
                    }

                    // 最后设置
                    m_bIsValueChange = false;
                }
                else
                    keyArray = m_KeyArray;

                // 清空
                m_SortedList.Clear();
                m_KeyArray = s_ZeroKeyArray;
                m_ValueArray = s_ZeroValueArray;
                m_KeyValuePairArray = s_ZeroKeyValuePairArray;
            }
            finally
            {
                m_LockSortedList.ExitWriteLock();
            }

            return keyArray;
        }
        #endregion

        #region zh-CHS 接口实现 | en Interface Implementation
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IEnumerator<KeyValuePair<KeyT, ValueT>> GetEnumerator()
        {
            KeyValuePair<KeyT, ValueT>[] tempValueArray = this.ToArray();
            if ( tempValueArray == null )
                yield break;

            for ( int iIndex = 0; iIndex < tempValueArray.Length; iIndex++ )
                yield return tempValueArray[iIndex];
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        #endregion
    }
}
#endregion